import './index.css'
import * as THREE from 'three'
import * as dat from 'dat.gui'
import {
  GLTFLoader
} from 'three/examples/jsm/Addons.js'
import {
  OrbitControls
} from 'three/examples/jsm/controls/OrbitControls'

/**
 * Size
 */
const Size = {
  width: window.innerWidth,
  height: window.innerHeight
}

/**
 * Camera
 */
const camera = new THREE.PerspectiveCamera(75, Size.width / Size.height, 0.1, 100)
camera.position.set(5, 5, 5)


/**
 * Scene
 */
const scene = new THREE.Scene()

/**
 * Light
 */
const ambientLight = new THREE.AmbientLight(0xffffff, 3)
scene.add(ambientLight)

const directionalLight = new THREE.DirectionalLight(0xffffff, 3)
directionalLight.position.set(6, 6, 6)
directionalLight.castShadow = true
// const helper = new THREE.CameraHelper(directionalLight.shadow.camera);
// scene.add(helper);
// 新增阴影相机配置
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.camera.left = -15;
directionalLight.shadow.camera.right = 15;
directionalLight.shadow.camera.top = 15;
directionalLight.shadow.camera.bottom = -15;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 50;
directionalLight.shadow.camera.updateMatrixWorld(); // 更新矩阵
scene.add(directionalLight)

/**
 * Plane
 */
const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshStandardMaterial({
  color: '#607D8B',
}))
plane.rotation.x = -Math.PI / 2
plane.receiveShadow = true;
scene.add(plane)

/**
 * Renderer
 */
const canvas = document.querySelector('canvas.webgl')
const renderer = new THREE.WebGLRenderer({
  canvas,
  antialias: true,
})
renderer.setSize(Size.width, Size.height)
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap

/**
 * Models
 */
let mixer, actionSurvey, actionWalk, actionRun, surveyWeight, walkWeight, runWeight;
const gltfLoader = new GLTFLoader()
gltfLoader.load(
  './assets/models/Fox/glTF/Fox.gltf',
  (gltf) => {
    console.log('success')
    console.log(gltf)
    const model = gltf.scene
    model.scale.set(0.02, 0.02, 0.02)

    // 添加动画
    mixer = new THREE.AnimationMixer(model)
    actionSurvey = mixer.clipAction(gltf.animations[0])
    actionWalk = mixer.clipAction(gltf.animations[1])
    actionRun = mixer.clipAction(gltf.animations[2])

    // 设置动画权重
    actionWalk.setEffectiveWeight(0)
    actionRun.setEffectiveWeight(0)

    actionSurvey.play()
    actionWalk.play()
    actionRun.play()

    createGUIPanel() // 创建 GUI 面板

    // 递归添加阴影
    model.traverse((child) => {
      if (child.isMesh) {
        child.castShadow = true
        child.receiveShadow = true
      }
    })
    scene.add(model)
  },
  (progress) => {
    console.log('progress')
  },
  (error) => {
    console.log(error)
  }
)

/**
 * OrbitControls
 */
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true


/**
 * createGUIPanel
 */
const gui = new dat.GUI()
const createGUIPanel = () => {
  const animationFolder = gui.addFolder('Animation')

  const executeCrossFade = (startAction, endAction, durition = 3) => {
    endAction.enabled = true;
    endAction.time = 0;
    endAction.setEffectiveWeight(1)
    startAction.crossFadeTo(endAction, durition, 3)
  }

  const guiObj = {
    surveyToWalk: () => {
      executeCrossFade(actionSurvey, actionWalk)
    },
    walkToRun: () => {
      executeCrossFade(actionWalk, actionRun)
    },
    runToWalk: () => {
      executeCrossFade(actionRun, actionWalk)
    },
    walkToSurvey: () => {
      executeCrossFade(actionWalk, actionSurvey)
    },
  }

  animationFolder.add(guiObj, 'surveyToWalk')
  animationFolder.add(guiObj, 'walkToRun')
  animationFolder.add(guiObj, 'runToWalk')
  animationFolder.add(guiObj, 'walkToSurvey')
}


/**
 * Update
 */
let elpasedTime;
let currentTime = 0;
let clock = new THREE.Clock();
const tick = () => {
  elpasedTime = clock.getElapsedTime();
  let deltaTime = elpasedTime - currentTime;
  currentTime = elpasedTime;
  controls.update();
  if (mixer) {
    mixer.update(deltaTime)

    // if (actionSurvey) {
    //   surveyWeight = actionSurvey.getEffectiveWeight()
    // }

    // if (actionWalk) {
    //   walkWeight = actionWalk.getEffectiveWeight()
    // }

    // if (actionRun) {
    //   runWeight = actionRun.getEffectiveWeight()
    // }
  }
  renderer.render(scene, camera)
  requestAnimationFrame(tick)
}
tick()